home *** CD-ROM | disk | FTP | other *** search
- /*
- menus & windows.c
-
- This file contains the menu and window handling routines.
-
- Created 9/2/92 - Dave Hersey
-
- ----------------------------------------------
-
- 2/93 debugged and plopped on GX CD. - dmh
- 9/93 updated to run with the ß2 "GXified" interface files - PLA
- 5/94 Fixed some bad, bad, viewport-confused code. - dmh
- 8/94 Universalized. - dmh
- */
-
- #include <stdio.h>
- #include <events.h>
- #include <windows.h>
-
- #include <font library.h>
- #include <graphics libraries.h>
- #include <graphics toolbox.h>
- #include <graphics debugging.h>
- #include <qd library.h>
- #include <PrintingMessages.h>
- #include <PrintingManager.h>
- #include <PrintingResTypes.h>
-
- #include "Banana Jr.h"
-
- #define kOSEvent app4Evt /* event used by MultiFinder */
- #define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */
- #define kResumeMask 1 /* bit of message field for resume vs. suspend */
-
-
- /*------ DoDocInit ------------------------------------------------------------*/
- //
- // In this function we create and gxInitialize the the private document structure
- // for a new window. This structure contains the print job and one page gxShape
- // initially. New pages may be added later. We store a handle to this data in
- // the window's refCon field for easy retrieval. By doing this rather than using
- // globals, we can create many windows containing unique print jobs, formats and
- // pages.
- //
- OSErr DoDocInit(wind)
- WindowPtr wind;
- {
- OSErr err;
- gxJob docJob = nil;
- TH_Doc windDoc = nil;
- short newPage;
-
- // Create a print job for this document. This will be the same as the system
- // default until the user goes through the dialogs for Page Setup or Print…
-
- err = GXNewJob(&docJob);
-
-
- // If there are no errors, install our overrides for the format dialog (which
- // will add our panel to it) and gxPrintingEvent (which will allow us to update
- // our windows as the printing dialogs are moved around. Create a handle the
- // size of our document structure and store the print job and one page description
- // in it. Store the handle in the window's refCon field so that we can get at it.
- // (Note that the utility routines "GetDocJob" and "GetDocShape" can be used to do
- // this easily.)
-
-
- if (!err)
- {
- GXInstallApplicationOverride(docJob, gxFormatDialog, NewGXFormatDialogProc(PageFormatDialog));
- GXInstallApplicationOverride(docJob, gxPrintingEvent, NewGXPrintingEventProc(MyPrintingEventOverride));
-
- windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
-
- if (!windDoc)
- err = MemError();
- else
- {
- (*windDoc)->docJob = docJob;
- (*windDoc)->numPages = 0;
- (*windDoc)->curPage = 1;
-
- newPage = 1;
-
- (*windDoc)->window = wind;
- (*windDoc)->viewPort = GXNewWindowViewPort(wind);
- err = AddPage(windDoc, &newPage);
-
- if (!err)
- SetWRefCon(wind, (long) windDoc);
- }
- }
-
- if (err)
- {
- if (windDoc) DisposeHandle((Handle)windDoc);
- if (docJob) GXDisposeJob(docJob);
- }
-
- return err;
- }
-
-
- /*------ DoDraw ---------------------------------------------------------------------------------------*/
- //
- // Draw the contents of the window.
- //
- void DoDraw(wind)
- WindowPtr wind;
- {
- TH_Doc doc;
- gxShape pageShape;
- short curPage;
-
- doc = GetDoc(wind);
- curPage = (*doc)->curPage;
-
- GXDrawShape(GetDocShape(doc, curPage));
- }
-
-
- /*------ CreateSampleImage ----------------------------------------------------------------------------*/
- //
- // This function adds a simple shape to the page indicated
- // in the passed document.
- //
- void CreateSampleImage(TH_Doc doc, short whichPg)
- {
- TH_Page docPage;
- gxShape pageShape, theText;
- gxColor textColor;
- Str255 textStr;
- unsigned char numChars, loop;
- short numPages;
-
- numPages = (*doc)->numPages;
-
- // Retrieve the page gxShape so we can add to it.
-
- docPage = GetDocPage(doc, whichPg);
- pageShape = (*docPage)->pageShape;
-
- numChars = sprintf((Ptr) &textStr[0], "%s %i %s", "This was added when there were", numPages -1, "pages");
- theText = GXNewText(numChars, (unsigned char *) textStr, nil);
- SetShapeCommonFont(theText, timesFont);
- GXSetShapeTextSize(theText, ff(30));
- GXMoveShapeTo (theText, ff(10), ff(30));
-
- // Create an hsv gxColor space
-
- textColor.space = gxHSVSpace;
- textColor.profile = nil;
- textColor.element.hsv.hue = 0x7400;
- textColor.element.hsv.saturation = 0xFFFF;
- textColor.element.hsv.value = 0xFFFF;
-
- for (loop = 1; loop < 14; loop++)
- {
- GXSetShapeColor(theText, &textColor);
- AddToShape(pageShape, theText);
- if (loop < 7)
- GXMoveShape(theText, ff(10), ff(35));
- else
- GXMoveShape(theText, ff(-10), ff(35));
- textColor.element.hsv.hue += 0x0800;
- }
-
- GXDisposeShape(theText);
- }
-
-
- /*------ DoCreateNew ---------------------------------------------------------------------------------*/
- //
- // This routine is called when a window needs to be created.
- //
- OSErr DoCreateNew(void)
- {
- OSErr err;
- WindowPtr wind;
-
- /** Create a window, attach a default viewPort to it, create and initialize our private data for it, and
- /** add a sample image to its page shape. **/
-
- wind = NewWindow(nil, &gWindowQDRect, gWindowTitle, true, noGrowDocProc, (WindowPtr)-1L, true, 0L);
-
- if (!wind)
- err = MemError();
- else
- err = DoDocInit(wind);
-
- // Invalidate the window's portRect so that everything gets updated.
-
- SetPort(wind);
- InvalRect(&wind->portRect);
- return err;
- }
-
-
- /*------ DoDispose -------------------------------------------------------------------------------------*/
- //
- // This routine is called when a window needs to be disposed of.
- //
- void DoDispose(WindowPtr wind)
- {
- TH_Doc doc;
- short numPages, pg;
-
- /**
- You should always dispose of your GX graphics objects before tossing your window. Why? It's generally good
- form and this approach guarantees that everything is disposed. If you had not disposed of everything, the
- call to DisposeWindow should dispose of the objects. If you are running the debugging version of the
- SecretGraphics init with notices set, you will receive a notice that you had not disposed of everything. You
- can turn notices on in this file by setting gDebugging = TRUE (above).
- **/
-
- doc = GetDoc(wind); // Get the handle to our document structure.
- numPages = (*doc)->numPages; // Get the number of pages in our document.
-
- for (pg = numPages; pg >= 1; pg--)
- DisposePage(doc, pg); // Dispose of each page's info and shapes.
-
- GXDisposeJob(GetDocJob(doc)); // Dispose of this doc's print job.
- DisposHandle((Handle) doc); // Dispose of our private data.
- DisposeWindow(wind); // Dispose of the window.
- }
-
-
-
- /*------ AddPage -------------------------------------------------------------------------------------*/
- //
- // This routine is called when a page needs to be added to a document. The
- // page is added AFTER the page number passed. If whichPg is greater than
- // the last page, the new page is added to the end of the document. If
- // whichPg is less than 1, the page is added to the beginning of the doc.
- // The page number of the new page is returned in whichPg.
- //
- OSErr AddPage(TH_Doc doc, short *whichPg)
- {
- OSErr err;
- gxJob docJob = nil;
- gxShape pageShape = nil;
- TH_Page docPage;
- TH_Page page;
- short numPages;
- short aPage;
- long newSize;
-
- numPages = (*doc)->numPages;
-
- // Pin the page number to insert after to the range (0, numPages).
-
- *whichPg = (*whichPg < 1)? 0: (*whichPg < numPages)? *whichPg: numPages;
-
- // Create the page gxShape. We set the unique items attribute to make sure that each
- // item added to the picture has a unique reference.
-
- pageShape = GXNewShape(gxPictureType);
- GXSetShapeViewPorts(pageShape, 1, &(*doc)->viewPort);
- GXSetShapeAttributes(pageShape, GXGetShapeAttributes(pageShape) | gxUniqueItemsShape);
-
- docPage = (TH_Page) NewHandleClear(sizeof(T_Page));
-
- if (!docPage)
- err = MemError();
- else
- {
- newSize = GetHandleSize((Handle) doc) + sizeof(T_Page);
- SetHandleSize((Handle) doc, newSize);
- err = MemError();
-
- if (!err)
- {
- (*docPage)->pageFormat = GXNewFormat((*doc)->docJob);
- (*docPage)->pageShape = pageShape;
- numPages = ++(*doc)->numPages;
- ++*whichPg;
-
- if ((*whichPg < numPages) && (numPages > 1))
- for (aPage = numPages; aPage > *whichPg; aPage--)
- (*doc)->docPage[aPage -1] = (*doc)->docPage[aPage -2];
-
- (*doc)->docPage[*whichPg -1] = docPage;
- CreateSampleImage(doc, *whichPg);
- }
- }
-
- return err;
- }
-
-
-
- /*------ DisposePage -------------------------------------------------------------------------------------*/
- //
- // This routine is called when a page in a document needs to be disposed of.
- // It's smart enough to allow you to delete a page from the middle of the
- // document, not just from the end.
- //
- void DisposePage(TH_Doc doc, short whichPg)
- {
- TH_Page page;
- short numPages;
- short pageNum;
- long newSize;
-
- if (whichPg > (*doc)->numPages) return; // ?! There aren't that many pages!!
- if (whichPg < 1) return; // ?! Page numbers start at 1!!
-
- page = GetDocPage(doc, whichPg); // Get the page in question and
- GXDisposeShape((*page)->pageShape); // delete its gxShape,
- GXDisposeFormat((*page)->pageFormat); // format,
- DisposeHandle((Handle) page); // and free up the memory it occupies.
-
- numPages = --(*doc)->numPages; // We now have one less page in our document.
-
-
- // If the page we deleted was not at the end of the document, we need to move
- // all following pages down one. In other words, if page 5 is deleted, page 6
- // becomes page 5, page 7 becomes page 6 and so forth. When done, resize the
- // handle to the document's info, since we no longer need the room occupied by
- // the deleted page's info.
-
- if (whichPg <= numPages)
- {
- for (pageNum = whichPg; pageNum <= numPages +1; pageNum++)
- (*doc)->docPage[pageNum -1] = (*doc)->docPage[pageNum];
-
- newSize = GetHandleSize((Handle) doc) - sizeof(T_Page);
- SetHandleSize((Handle) doc, newSize);
- }
- }
-
-
-
- /*------ EventLoop ------------------------------------------------------------------------------------*/
-
- void EventLoop()
- {
- EventRecord theEvent;
-
- if (WaitNextEvent(everyEvent, &theEvent, gSleep, nil))
- MyDoEvent(&theEvent);
- }
-
-
- /*------ DoEvent ------------------------------------------------------------------------------------*/
-
- void MyDoEvent(EventRecord *theEvent)
- {
- char key;
- WindowPtr whichWindow;
- GrafPtr oldPort;
-
- switch(theEvent->what)
- {
- case updateEvt:
- if (((WindowPeek) theEvent->message)->windowKind == userKind)
- {
- GetPort(&oldPort);
- SetPort((WindowPtr) theEvent->message);
- BeginUpdate((WindowPtr) theEvent->message);
- DoDraw((WindowPtr) theEvent->message);
- EndUpdate((WindowPtr) theEvent->message);
- SetPort(oldPort);
- }
- break;
-
- case mouseDown:
- switch (FindWindow(theEvent->where, &whichWindow)) {
- case inSysWindow:
- SystemClick(theEvent, whichWindow);
- break;
-
- case inDrag:
- if (((WindowPeek) whichWindow)->windowKind == userKind)
- DragWindow(whichWindow, theEvent->where, &qd.screenBits.bounds);
- break;
-
- case inGoAway:
- if ((((WindowPeek) whichWindow)->windowKind == userKind) &&
- (TrackGoAway(whichWindow, theEvent->where)))
- DoDispose(whichWindow);
- break;
-
- case inContent:
- if (((WindowPeek) whichWindow)->windowKind == userKind)
- SelectWindow(whichWindow);
- break;
- case inMenuBar:
- DoMenuCommand(MenuSelect(theEvent->where));
- break;
-
- }
-
- case keyDown:
- case autoKey:
- key = theEvent->message & charCodeMask;
- if (theEvent->modifiers & cmdKey)
- if (theEvent->what == keyDown)
- DoMenuCommand(MenuKey(key));
- break;
-
- case kOSEvent:
- switch ((unsigned long) theEvent->message >> 24) { /** high byte of message **/
- case kSuspendResumeMessage: /** suspend/resume is also an activate/deactivate **/
- if ((theEvent->message & kResumeMask) == 0)
- gSleep = 80; /** we are headed to the background, so slow down... **/
- else
- {
- gSleep = 0; /** we are headed to the foreground, so speed up... **/
-
- // On a resume event, we need to call GXUpdateJob on all of our documents'
- // jobs. This is important because the user may have just changed
- // something which affects our jobs (like the size of the paper in the
- // printer).
- //
- // Since our application stores our document references in the refCon fields
- // of our documents' windows, we just loop through every one of our windows,
- // extract our document pointers and update the associated jobs.
-
- whichWindow = FrontWindow();
-
- while (whichWindow != nil)
- {
- if (((WindowPeek) whichWindow)->windowKind == userKind)
- GXUpdateJob(GetDocJob(GetDoc(whichWindow)));
-
- whichWindow = (WindowPtr) ((WindowPeek) whichWindow)->nextWindow;
- }
- }
- break;
- }
- break;
- }
- }
-
-
- /*------ DoMenuCommand ---------------------------------------------------------------------------------------*/
- //
- // This routine handles the dispatching of our menu requests.
- //
- void DoMenuCommand(long menuResult)
- {
- short menuID;
- short menuItem;
- Str255 daName;
- OSErr err;
- gxDialogResult result;
- TH_Doc doc;
- short curPage, numPages, newPage;
- WindowPtr wind;
-
- menuID = menuResult >>16;
- menuItem = menuResult & 0x0000ffff;
-
- switch (menuID)
- {
- case mApple:
- switch (menuItem)
- {
- case iAbout: /* display About box */
- break;
-
- default: /* handle DA selection */
- GetItem(GetMHandle(mApple), menuItem, daName);
- OpenDeskAcc(daName);
- break;
- }
- break;
-
- case mFile:
- switch (menuItem)
- {
- case iNew:
- /* create new window */
-
- err = DoCreateNew();
- break;
-
- case iOpen:
- /* open saved window */
-
- break;
-
- case iClose:
- /* close front window */
-
- DoDispose(FrontWindow());
- break;
-
- case iSave:
- /* save front window */
-
- break;
-
- case iDocSetup:
- /* perform document setup */
-
- HiliteMenu(0);
- err = DoDocFormat(FrontWindow(), &result);
- break;
-
- case iPageSetup:
- /* perform page setup */
-
- HiliteMenu(0);
- err = DoPageFormat(FrontWindow(), &result);
- break;
-
- case iPrintOne:
- /* perform print one copy */
-
- err = MyPrintOneCopy(FrontWindow());
- break;
-
- case iPrint:
- /* perform print */
-
- HiliteMenu(0);
- err = DoPrinting(FrontWindow());
- break;
-
- case iQuit:
- gQuitting = true;
- break;
- }
- break;
-
- case mEdit:
- break;
-
- case mDocument:
- switch (menuItem)
- {
- case iAddPage:
- /* Add a page */
-
- wind = FrontWindow();
- SetPort(wind);
- doc = GetDoc(wind);
- newPage = (*doc)->curPage;
- AddPage(doc, &newPage);
- (*doc)->curPage = newPage;
- EraseRect(&wind->portRect);
- InvalRect(&wind->portRect);
- break;
-
- case iDeletePage:
- /* Delete current page */
-
- wind = FrontWindow();
- SetPort(wind);
- doc = GetDoc(wind);
- curPage = (*doc)->curPage;
- numPages = (*doc)->numPages;
-
- if (numPages > 1)
- {
- DisposePage(doc, curPage);
-
- if (curPage == numPages)
- curPage = --(*doc)->curPage;
-
- EraseRect(&wind->portRect);
- InvalRect(&wind->portRect);
- }
- break;
-
- case iNextPage:
- /* Forward one page */
-
- wind = FrontWindow();
- SetPort(wind);
- doc = GetDoc(wind);
- curPage = (*doc)->curPage;
- numPages = (*doc)->numPages;
-
- if (curPage < numPages)
- {
- ++(*doc)->curPage;
-
- EraseRect(&wind->portRect);
- InvalRect(&wind->portRect);
- }
- break;
-
- case iPrevPage:
- /* Back one page */
-
- wind = FrontWindow();
- SetPort(wind);
- doc = GetDoc(wind);
- curPage = (*doc)->curPage;
-
- if (curPage > 1)
- {
- --(*doc)->curPage;
-
- EraseRect(&wind->portRect);
- InvalRect(&wind->portRect);
- }
- break;
- }
- break;
- }
- HiliteMenu(0);
- }
-
-
- /*------ GetDoc --------------------------------------------------------------------------------------*/
- //
- // This utility routine returns the document structure attached to a window.
- //
- TH_Doc GetDoc(WindowPtr wind)
- {
- TH_Doc doc = nil;
-
- if (wind) doc = (TH_Doc) GetWRefCon(wind);
-
- return doc;
- }
-
-
- /*------ GetDocPage ----------------------------------------------------------------------------------*/
- //
- // This utility routine returns the specified page structure for the passed document.
- //
- TH_Page GetDocPage(TH_Doc doc, short whichPg)
- {
- TH_Page page;
-
- page = (*doc)->docPage[whichPg -1];
-
- return page;
- }
-
-
- /*------ GetDocShape ---------------------------------------------------------------------------------*/
- //
- // This utility routine returns the page gxShape (contents) attached to a window's document.
- //
- gxShape GetDocShape(TH_Doc doc, short whichPg)
- {
- TH_Page docPage;
- gxShape pageShape = nil;
-
- docPage = (*doc)->docPage[whichPg -1];
- pageShape = (*docPage)->pageShape;
-
- return pageShape;
- }
-
-
- /*------ GetDocJob -----------------------------------------------------------------------------------*/
- //
- // This utility routine returns the print job attached to a window's document.
- //
- gxJob GetDocJob(TH_Doc doc)
- {
- gxJob docJob = nil;
-
- docJob = (*doc)->docJob;
- return docJob;
- }
-